import {
    GetObjectOptions,
    GetObjectResult,
    HeadObjectResult,
    HeadOptions,
    Option,
    PutObjectOptions,
    PutObjectResult,
    RemoteStorage
} from './storage'
import OSS from 'ali-oss'
import path from 'path'
import axios from 'axios'
import logging from '../logging'

export class OSSStorage implements RemoteStorage {
    private ossClient: OSS;

    constructor(option: Option) {
        this.ossClient = new OSS({
            accessKeyId: option.accessKeyID,
            accessKeySecret: option.accessKeySecret,
            stsToken: option.securityToken,
            refreshSTSTokenInterval: 1000 * 3600, // for remove log: It's recommended to set 'refreshSTSToken' and 'refreshSTSTokenInterval' to refresh stsToken、accessKeyId、accessKeySecret automatically when sts token has expired
            bucket: option.bucket,
            endpoint: option.endpoint
        });
    }

    async stat(objectKey: string): Promise<boolean> {
        try {
            await this.ossClient.head(objectKey);
            return Promise.resolve(true);
        } catch (error) {
            // @ts-ignore
            step.warnV1(`error status ${error.status} name ${error.name} message ${error.message}`)
            return Promise.resolve(false);
        }
    }

    async head(objectKey: string, options?: HeadOptions): Promise<HeadObjectResult> {
        return this.ossClient.head(objectKey, options);
    }

    async put(objectKey: string, filePath: string, options?: PutObjectOptions): Promise<PutObjectResult> {
        // local filePath -> oss objectKey
        return this.ossClient.put(objectKey, path.normalize(filePath), options);
    }

    async get(objectKey: string, filePath: string, options?: GetObjectOptions): Promise<GetObjectResult> {
        // oss objectKey -> local filePath
        return this.ossClient.get(objectKey, path.normalize(filePath), options);
    }
}

export async function getEndpoint(endpoint: string): Promise<string> {
    if (endpoint) {
        logging.debug(`use inputted endpoint ${endpoint}`)
        return endpoint;
    }

    let flowOssEndpointInternal = process.env['FLOW_OSS_ENDPOINT_INTERNAL']
    let flowOssEndpointInternet = process.env['FLOW_OSS_ENDPOINT_INTERNET']
    logging.debug(`use flowOssEndpointInternal ${flowOssEndpointInternal}`)
    logging.debug(`use flowOssEndpointInternet ${flowOssEndpointInternet}`)

    if(!flowOssEndpointInternal){
        flowOssEndpointInternal = "oss-cn-beijing-internal.aliyuncs.com";
    }
    if(!flowOssEndpointInternet){
        flowOssEndpointInternet = "oss-cn-beijing.aliyuncs.com";
    }


    let relEndpoint = "";
    try {
        await axios.get(`https://${flowOssEndpointInternal}`, {timeout: 1000});
        relEndpoint = flowOssEndpointInternal;
    } catch (error) {
        // @ts-ignore
        if(error.status && error.status==403){
            relEndpoint = flowOssEndpointInternal;
        }else{
            if('true' == process.env['useForeignCluster']){
                relEndpoint = 'oss-accelerate.aliyuncs.com'
            }else {
                relEndpoint = flowOssEndpointInternet
            }
        }

    }
    logging.info(`use relEndpoint ${relEndpoint}`)
    return Promise.resolve(relEndpoint);
}